{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "This tutorial demostrates Pointer Networks with readable code."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import math\n",
    "import numpy as np\n",
    "\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import torch.autograd as autograd\n",
    "import torch.nn.functional as F\n",
    "from torch.autograd import Variable\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "\n",
    "USE_CUDA = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from IPython.display import clear_output\n",
    "from tqdm import tqdm\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Generating dataset for sorting task</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "class SortDataset(Dataset):\n",
    "    \n",
    "    def __init__(self, data_len, num_samples, random_seed=111):\n",
    "        super(SortDataset, self).__init__()\n",
    "        torch.manual_seed(random_seed)\n",
    "\n",
    "        self.data_set = []\n",
    "        for _ in tqdm(range(num_samples)):\n",
    "            x = x = torch.randperm(data_len)\n",
    "            self.data_set.append(x)\n",
    "\n",
    "        self.size = len(self.data_set)\n",
    "\n",
    "    def __len__(self):\n",
    "        return self.size\n",
    "\n",
    "    def __getitem__(self, idx):\n",
    "        return self.data_set[idx]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_size = 1000\n",
    "val_size = 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 1000/1000 [00:00<00:00, 23103.26it/s]\n",
      "100%|██████████| 100/100 [00:00<00:00, 188338.75it/s]\n"
     ]
    }
   ],
   "source": [
    "train_dataset = SortDataset(10, train_size)\n",
    "val_dataset   = SortDataset(10, val_size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Attention mechanism</h3>\n",
    "<p>\n",
    "Using two types of attention mechanism: \"Dot\" and \"Bahdanau\" . More details in <a href=\"http://aclweb.org/anthology/D15-1166\">Effective Approaches to Attention-based Neural Machine Translation</a></p>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "a_t(s) = align(h_t, \\bar h_s)  = \\dfrac{exp(score(h_t, \\bar h_s))}{\\sum_{s'} exp(score(h_t, \\bar h_{s'}))}\n",
    "$$\n",
    "\n",
    "$$\n",
    "score(h_t, \\bar h_s) =\n",
    "\\begin{cases}\n",
    "h_t ^\\top \\bar h_s & Dot \\\\\n",
    "v_a ^\\top \\tanh(\\textbf{W}_a [ h_t ; \\bar h_s ]) & Bahdanau\n",
    "\\end{cases}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class Attention(nn.Module):\n",
    "    def __init__(self, hidden_size, use_tanh=False, C=10, use_cuda=USE_CUDA):\n",
    "        super(Attention, self).__init__()\n",
    "        \n",
    "        self.use_tanh = use_tanh\n",
    "        self.W_query = nn.Linear(hidden_size, hidden_size)\n",
    "        self.W_ref   = nn.Conv1d(hidden_size, hidden_size, 1, 1)\n",
    "        self.C = C\n",
    "        \n",
    "        V = torch.FloatTensor(hidden_size)\n",
    "        if use_cuda:\n",
    "            V = V.cuda()  \n",
    "        self.V = nn.Parameter(V)\n",
    "        self.V.data.uniform_(-(1. / math.sqrt(hidden_size)) , 1. / math.sqrt(hidden_size))\n",
    "        \n",
    "    def forward(self, query, ref):\n",
    "        \"\"\"\n",
    "        Args: \n",
    "            query: [batch_size x hidden_size]\n",
    "            ref:   ]batch_size x seq_len x hidden_size]\n",
    "        \"\"\"\n",
    "        \n",
    "        batch_size = ref.size(0)\n",
    "        seq_len    = ref.size(1)\n",
    "\n",
    "        ref = ref.permute(0, 2, 1)\n",
    "        query = self.W_query(query).unsqueeze(2)  # [batch_size x hidden_size x 1]\n",
    "        ref   = self.W_ref(ref)  # [batch_size x hidden_size x seq_len] \n",
    "\n",
    "        expanded_query = query.repeat(1, 1, seq_len) # [batch_size x hidden_size x seq_len]\n",
    "        V = self.V.unsqueeze(0).unsqueeze(0).repeat(batch_size, 1, 1) # [batch_size x 1 x hidden_size]\n",
    "\n",
    "        logits = torch.bmm(V, F.tanh(expanded_query + ref)).squeeze(1)\n",
    "        \n",
    "        if self.use_tanh:\n",
    "            logits = self.C * F.tanh(logits)\n",
    "        else:\n",
    "            logits = logits  \n",
    "        return ref, logits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Pointer Network</h3>\n",
    "<p><a href=\"https://arxiv.org/abs/1506.03134\">Pointer Networks\n",
    "</a></p>\n",
    "<p>The model solves the problem of variable size output dictionaries using a recently proposed mechanism of neural attention. It differs from the previous attention attempts in that, instead of using attention to blend hidden units of an encoder to a context vector at each decoder step, it uses attention as a pointer to select a member of the input sequence as the output.</p>\n",
    "<img src=\"./imgs/Снимок экрана 2017-12-26 в 4.30.58 ДП.png\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class PointerNet(nn.Module):\n",
    "    def __init__(self, \n",
    "            embedding_size,\n",
    "            hidden_size,\n",
    "            seq_len,\n",
    "            n_glimpses,\n",
    "            tanh_exploration,\n",
    "            use_tanh,\n",
    "            use_cuda=USE_CUDA):\n",
    "        super(PointerNet, self).__init__()\n",
    "        \n",
    "        self.embedding_size = embedding_size\n",
    "        self.hidden_size    = hidden_size\n",
    "        self.n_glimpses     = n_glimpses\n",
    "        self.seq_len        = seq_len\n",
    "        self.use_cuda       = use_cuda\n",
    "        \n",
    "        \n",
    "        self.embedding = nn.Embedding(seq_len, embedding_size)\n",
    "        self.encoder = nn.LSTM(embedding_size, hidden_size, batch_first=True)\n",
    "        self.decoder = nn.LSTM(embedding_size, hidden_size, batch_first=True)\n",
    "        self.pointer = Attention(hidden_size, use_tanh=use_tanh, C=tanh_exploration, use_cuda=use_cuda)\n",
    "        self.glimpse = Attention(hidden_size, use_tanh=False, use_cuda=use_cuda)\n",
    "        \n",
    "        self.decoder_start_input = nn.Parameter(torch.FloatTensor(embedding_size))\n",
    "        self.decoder_start_input.data.uniform_(-(1. / math.sqrt(embedding_size)), 1. / math.sqrt(embedding_size))\n",
    "        \n",
    "        self.criterion = nn.CrossEntropyLoss()\n",
    "        \n",
    "    def apply_mask_to_logits(self, logits, mask, idxs): \n",
    "        batch_size = logits.size(0)\n",
    "        clone_mask = mask.clone()\n",
    "\n",
    "        if idxs is not None:\n",
    "            clone_mask[[i for i in range(batch_size)], idxs.data] = 1\n",
    "            logits[clone_mask] = -np.inf\n",
    "        return logits, clone_mask\n",
    "            \n",
    "    def forward(self, inputs, target):\n",
    "        \"\"\"\n",
    "        Args: \n",
    "            inputs: [batch_size x sourceL]\n",
    "        \"\"\"\n",
    "        batch_size = inputs.size(0)\n",
    "        seq_len    = inputs.size(1)\n",
    "        assert seq_len == self.seq_len\n",
    "        \n",
    "        embedded = self.embedding(inputs)\n",
    "        target_embedded = self.embedding(target)\n",
    "        encoder_outputs, (hidden, context) = self.encoder(embedded)\n",
    "        \n",
    "        mask = torch.zeros(batch_size, seq_len).byte()\n",
    "        if self.use_cuda:\n",
    "            mask = mask.cuda()\n",
    "            \n",
    "        idxs = None\n",
    "       \n",
    "        decoder_input = self.decoder_start_input.unsqueeze(0).repeat(batch_size, 1)\n",
    "        \n",
    "        loss = 0\n",
    "        \n",
    "        for i in range(seq_len):\n",
    "            \n",
    "            \n",
    "            _, (hidden, context) = self.decoder(decoder_input.unsqueeze(1), (hidden, context))\n",
    "            \n",
    "            query = hidden.squeeze(0)\n",
    "            for i in range(self.n_glimpses):\n",
    "                ref, logits = self.glimpse(query, encoder_outputs)\n",
    "                logits, mask = self.apply_mask_to_logits(logits, mask, idxs)\n",
    "                query = torch.bmm(ref, F.softmax(logits).unsqueeze(2)).squeeze(2) \n",
    "                \n",
    "                \n",
    "            _, logits = self.pointer(query, encoder_outputs)\n",
    "            logits, mask = self.apply_mask_to_logits(logits, mask, idxs)\n",
    "            \n",
    "            decoder_input = target_embedded[:,i,:]\n",
    "            \n",
    "            loss += self.criterion(logits, target[:,i])\n",
    "            \n",
    "            \n",
    "        return loss / seq_len"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "pointer = PointerNet(embedding_size=32, hidden_size=32, seq_len=10, n_glimpses=1, tanh_exploration=10, use_tanh=True)\n",
    "adam = optim.Adam(pointer.parameters(), lr=1e-4)\n",
    "\n",
    "if USE_CUDA:\n",
    "    pointer = pointer.cuda()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "train_loader = DataLoader(train_dataset, batch_size=1, shuffle=True, num_workers=1)\n",
    "val_loader   = DataLoader(val_dataset, batch_size=1, shuffle=True, num_workers=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Train and Validate</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false,
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\nEARBEAKU/wc96ASxxhbKmwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fa651cb9c90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "n_epochs = 1\n",
    "train_loss = []\n",
    "val_loss   = []\n",
    "\n",
    "for epoch in range(n_epochs):\n",
    "    for batch_id, sample_batch in enumerate(train_loader):\n",
    "\n",
    "        inputs = Variable(sample_batch)\n",
    "        target = Variable(torch.sort(sample_batch)[0])\n",
    "        if USE_CUDA:\n",
    "            inputs = inputs.cuda()\n",
    "            target = target.cuda()\n",
    "\n",
    "        loss = pointer(inputs, target)\n",
    "\n",
    "        adam.zero_grad()\n",
    "        loss.backward()\n",
    "        adam.step()\n",
    "        \n",
    "        train_loss.append(loss.data[0])\n",
    "\n",
    "        if batch_id % 10 == 0:\n",
    "\n",
    "            clear_output(True)\n",
    "            plt.figure(figsize=(20,5))\n",
    "            plt.subplot(131)\n",
    "            plt.title('train epoch %s loss %s' % (epoch, train_loss[-1] if len(train_loss) else 'collecting'))\n",
    "            plt.plot(train_loss)\n",
    "            plt.grid()\n",
    "            plt.subplot(132)\n",
    "            plt.title('val epoch %s loss %s' % (epoch, val_loss[-1] if len(val_loss) else 'collecting'))\n",
    "            plt.plot(val_loss)\n",
    "            plt.grid()\n",
    "            plt.show()\n",
    "        \n",
    "        if batch_id % 100 == 0:\n",
    "            pointer.eval()\n",
    "            for val_batch in val_loader:\n",
    "                inputs = Variable(val_batch)\n",
    "                target = Variable(torch.sort(val_batch)[0])\n",
    "                if USE_CUDA:\n",
    "                    inputs = inputs.cuda()\n",
    "                    target = target.cuda()\n",
    "\n",
    "                loss = pointer(inputs, target)\n",
    "                val_loss.append(loss.data[0])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
